package com.awspaas.user.apps.cpq.controller;



import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.poi.ss.usermodel.*;

import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.commons.mvc.view.ResponseObject;
import com.actionsoft.bpms.server.UserContext;
import com.actionsoft.sdk.local.SDK;

public class CPQ_GetModuleNumberWeb {

	public String getModuleNumber(UserContext userContext, String bindId, String mkbh,String id) throws Exception {
		try {
			/**
			 * 获取当前项目的基本参数对应值
			 */
			BO pData = SDK.getBOAPI().query("BO_EU_CPQ_PROJECT_MSG").bindId(bindId).detail();
			BO moduleData = SDK.getBOAPI().query("BO_EU_CPQ_PROJECT_MSG_GRIDS").addQuery("ID=", id).detail();
			// 获取项目基本参数字段映射数据
			List<BO> ppDatas = SDK.getBOAPI().query("BO_EU_CPQ_PROJECT_PARAMETER_MAP").list();
			// 将参数编号和参数值存放在map中
			Map<String, String> pMap = new HashMap<String, String>();
			for (BO bo : ppDatas) {
				String value = pData.getString(bo.getString("DYZDMC"));// 获取参数值。
				String key = bo.getString("PARMENTIER_NO");// 获取参数对应在计算规则的编号。
				pMap.put(key, value);
			}
			/**
			 * 判断所选的模块是否为动态计算单价模板，如果是计算出模块在当前项目中的单价。
			 */
			BO data = SDK.getBOAPI().query("BO_EU_CPQ_MODULE_MSG").addQuery("MKBM=", mkbh).detail();
			String type = data.getString("SITRUE");// 是否动态计算单价模块
			double MKDJ = Double.parseDouble(data.getString("MKDJ"));// 模块单价
			// 如果是则进行动态计算
			if (type.equals("true")) {
				// 计算当前模块中物料明细的数量和物料的成本价格，根据物料明细的表中的计算规则进行计算。
				/**
				 * 获取模块中的物料明细，遍历物料明细判断当前物料是否是需要计算的，是则通过计算规则进行计算，如果不是则不需要计算。
				 */
				List<BO> materials = SDK.getBOAPI().query("BO_EU_CPQ_MODULE_MSG_GRID").bindId(data.getBindId()).list();
				Map<String, String> noMap = new HashMap<>();
				List<String> needEquations = new ArrayList<String>();
				if (materials.size() > 0) {
					for (BO bo : materials) {
						String equation = bo.getString("WLJSGS");
						if (!equation.equals("0")) {
							// 获取物料数量计算公式中参数代号，如果有则将代号存放在list中
							for (String key : pMap.keySet()) {
								int num = equation.indexOf(key);
								if (num > -1) {
									needEquations.add(key);
								}
							}

						}
					}
				}
				// 去重所需要的参数信息。
				Set<String> set = new HashSet<>(needEquations);
				List<String> equationsList = new ArrayList<>(set);
				if (equationsList.size() > 0) {
					for (int i = 0; i < equationsList.size(); i++) {
						int num = i + 1;
						noMap.put(equationsList.get(i), "B$" + num);
					}
				}
				/**
				 * 计算物料数量和成本。
				 */

				/************************** 通过excel公式进行计算 ***********************************/
				Map<String, BO> materMap = new HashMap<>();
				Workbook workbook = new XSSFWorkbook();
				// 创建公式评估器
				FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator();
				// 设置单元格值
				Sheet sheet = workbook.createSheet("Sheet1");
				for (int i = 0; i < equationsList.size(); i++) {
					int num = i + 1;
					Cell cellB1 = sheet.createRow(i).createCell(1);
					cellB1.setCellValue(pMap.get(equationsList.get(i)));
				}
				// 将物料中的计算规则的参数替换为指定的excel参数
				if (materials.size() > 0) {
					for (int i = 0; i < materials.size(); i++) {
						BO bo = materials.get(i);
						String equation = bo.getString("WLJSGS");
						if (!equation.equals("0")) {
							// 获取物料数量计算公式中参数代号，如果有则将代号存放在list中
							for (String key : pMap.keySet()) {
								int num = equation.indexOf(key);
								if (num > -1) {
									equation = equation.replace(key, noMap.get(key));
								}
							}
							// 计算出物料数量和当前模块的物料成本价格
							Cell cellB1 = sheet.createRow(i).createCell(2);
							cellB1.setCellFormula(equation);
							formulaEvaluator.evaluateFormulaCell(cellB1);
							// 获取公式计算结果
							CellValue cellValue = formulaEvaluator.evaluate(cellB1);
							System.out.println("The result of the formula is: " + cellValue.getNumberValue());
							String price = bo.getString("DJ");
							double total = Double.parseDouble(price) * cellValue.getNumberValue();
							// 将数量和成本价格放入物料map集合中
							bo.set("SL", cellValue.getNumberValue());
							bo.set("ZJ", total);
							materMap.put(bo.getString("WLBM"), bo);
						}
					}
				}
				// 计算出模块的单价，每个物料总价相加
				double mkPrice = 0;
				for (String key : materMap.keySet()) {
					BO bo = materMap.get(key);
					String zjString = bo.getString("ZJ");
					mkPrice = mkPrice + Double.parseDouble(zjString);
				}
				if (MKDJ == 0) {
					MKDJ = mkPrice;
				}
				/************************** 通过excel公式进行计算 ***********************************/
			}

			String rule = data.getString("SLJSGZ"); // 计算规则
			/**
			 * 计算模块数量。
			 */
			if (!rule.equals("0")) {
				// 获取模块数量计算公式中参数代号，如果有则将代号存放在list中
				List<String> needRules = new ArrayList<String>();
				for (String key : pMap.keySet()) {
					int num = rule.indexOf(key);
					if (num > -1) {
						needRules.add(key);
					}
				}
				// 去重所需要的参数信息。
				Set<String> set = new HashSet<>(needRules);
				List<String> needList = new ArrayList<>(set);
				Map<String, String> noMap = new HashMap<>();
				if (needList.size() > 0) {
					for (int i = 0; i < needList.size(); i++) {
						int num = i + 1;
						noMap.put(needList.get(i), "B$" + num);
					}
				}
				Map<String, BO> materMap = new HashMap<>();
				Workbook workbook = new XSSFWorkbook();
				// 创建公式评估器
				FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator();
				// 设置单元格值
				Sheet sheet = workbook.createSheet("Sheet1");
				for (int i = 0; i < needList.size(); i++) {
					int num = i + 1;
					Cell cellB1 = sheet.createRow(i).createCell(1);
					cellB1.setCellValue(pMap.get(needList.get(i)));
				}
				// 将物料中的计算规则的参数替换为指定的excel参数
				// 获取物料数量计算公式中参数代号，如果有则将代号存放在list中
				for (String key : pMap.keySet()) {
					int num = rule.indexOf(key);
					if (num > -1) {
						rule = rule.replace(key, noMap.get(key));
					}
				}
				// 计算出物料数量和当前模块的物料成本价格
				Cell cellB1 = sheet.createRow(0).createCell(2);
				cellB1.setCellFormula(rule);
				formulaEvaluator.evaluateFormulaCell(cellB1);
				// 获取公式计算结果
				CellValue cellValue = formulaEvaluator.evaluate(cellB1);
				System.out.println("The result of the formula is: " + cellValue.getNumberValue());
				double number = cellValue.getNumberValue();
				// 计算出模块数量后，需要计算出模块的管理费GLFY、制造费用ZZFY、体积TJ、重量ZL				
				String GLFY = "0."+data.getString("GLFY").replace(".", "");
				String ZZFY = "0."+data.getString("ZZFY").replace(".", "");
				String LR = "0."+data.getString("LR").replace(".", "");
				String SL = "0."+data.getString("SL").replace(".", "");
				String TJ = data.getString("TJ");
				String ZL = data.getString("ZL");
				// 将字符串转换为double类型
				// 管理费占单价的百分比
				double GLFY_price = Double.parseDouble(GLFY);
				double GLFYTotalPrice = number * GLFY_price*MKDJ;
				// 制造费占单价的百分比
				double ZZFY_price = Double.parseDouble(ZZFY);
				double ZZFYTotalPrice = number * ZZFY_price*MKDJ;
				// 利润占单价的百分比
				double LR_price = Double.parseDouble(LR);
				double LRTotalPrice = number * LR_price*MKDJ;
				// 税率费用占单价的百分比
				double SL_price = Double.parseDouble(SL);
				double SLTotalPrice = number * SL_price*MKDJ;
				// 总体积
				double TJNum = TJ.isEmpty()?0:Double.parseDouble(TJ);
				double TJTotalNum = number * TJNum;
				// 总重量
				double ZLNum = ZL.isEmpty()?0:Double.parseDouble(ZL);
				double ZLTotalNum = number * ZLNum;
				// 总成本价
				double MKDJ_price = MKDJ;
				double MKTotalPrice = number * MKDJ_price;
				//将计算好的数据放入选择的子表数据中，并更新当前数据。
				moduleData.set("DJ",MKDJ );//模块单价
				moduleData.set("TJ", TJTotalNum);//模块体积
				moduleData.set("ZL",ZLTotalNum );//模块重量
				moduleData.set("ZZFY", ZZFYTotalPrice);//模块制造费用
				moduleData.set("GLFY", GLFYTotalPrice);//模块管理费用
				moduleData.set("TAX_RATE_PRICE", SLTotalPrice);//税费
				moduleData.set("LR", LRTotalPrice);//利润
				moduleData.set("TAX_RATE",data.getString("SL") );//税率(%)
				moduleData.set("SL", number);//模块数量
				moduleData.set("DW", data.getString("GG"));//模块单位
				moduleData.set("ZJ", MKTotalPrice);//模块成价格
				moduleData.set("XDXH", data.getString("MKMC"));//选定型号
				moduleData.set("MKBH", data.getString("MKBM"));//模块编码
				SDK.getBOAPI().update("BO_EU_CPQ_PROJECT_MSG_GRIDS", moduleData);
			}

			ResponseObject ro = ResponseObject.newOkResponse();
			return ro.toString();
		} catch (Exception e) {
			throw e;
		}

	}

}
